//
//  streamStatus.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/7/10.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef streamStatus_hpp
#define streamStatus_hpp

#include <stdio.h>
#include <iostream>
#include <cctype>
#include <string>
#include <sstream>

using namespace std;

class StreamStatus {
    
    
public:
    
    StreamStatus(){
        
    }
    
    ~StreamStatus(){
        
    }
    
    void testStatus(){
        //        good()    Returns true if the goodbit is set (the stream is ok)
        //        bad()    Returns true if the badbit is set (a fatal error occurred)
        //        eof()    Returns true if the eofbit is set (the stream is at the end of a file)
        //        fail()    Returns true if the failbit is set (a non-fatal error occurred)
        //        clear()    Clears all flags and restores the stream to the goodbit state
        
        //检测用户输入的名字
        while (1) {
            
            //get user's name
            cout << "Enter your name:";
            string strName;
            getline(cin, strName);
            
            bool bRejected = false;
            
            for (int i = 0; i < strName.length() && !bRejected; ++i) {
                // If the current character is an alpha character, that's fine
                if (isalpha(strName[i])) {
                    continue;
                }
                
                //if it's a space,that's fine too
                if (strName[i] == ' ') {
                    continue;
                }
                
                //otherwise we're rejecting this input
                bRejected = true;
                
            }
            
            if (!bRejected) {
                break;
            }
            
        }
        
    }
    
    bool InutMatches(string strUserInput,string strTemplate){
//        函数匹配模板“（###）### - ####”
        if (strTemplate.length() != strUserInput.length()) {
            return false;
        }
        
        for (int i = 0; i < strUserInput.length(); ++i) {
            
            switch (strTemplate[i]) {
                case '#'://match a digit
                    if (!isdigit(strUserInput[i])) {
                        return false;
                    }
                    break;
                case '_'://match a whitespace
                    if (!isspace(strUserInput[i])) {
                        return false;
                    }
                    break;
                case '@'://match a letter
                    if (!isalpha(strUserInput[i])) {
                        return false;
                    }
                    break;
                case '?'://match a anything
                    break;
                default:
                    break;
            }
            
        }
        
        
        return true;
        /*
         StreamStatus ss;
         std::string strValue;
         while (1) {
         cout << "Enter a phoneNum(###) ###-####:";
         getline(std::cin, strValue);
         if (ss.InutMatches(strValue, "(###) ###-####")) {
         break;
         }
         }
         */
    }
    
    //获得用户输入的数字，并处理异常
    void TestNum(){
        int nAge;
        
        while (1) {
            
            cout << "Enter your age: ";
            cin >> nAge;
            
            int gcount = 0;
            
            if (cin.fail()) {
                cin.clear();
                cin.ignore(32767,'\n');
                
                gcount = static_cast<int>(cin.gcount());
                cout << gcount << "XXX" << endl;
                continue;
            }
            
            cin.ignore(32767,'\n');//防止 123df 的情况，流中还存在数据buffer
            
//  我们可以使用gcount（）函数来确定忽略了多少个字符。 如果我们的输入有效，gcount（）应该返回1（只有一个被丢弃的换行符）ignore（）不会影响cin.gcount()函数。
            gcount = static_cast<int>(cin.gcount());
            cout << gcount << endl;
            if (gcount > 1) {
                continue;
            }
            
            if (nAge <= 0) {
                continue;
            }
            
            break;
        }
        
        cout << "You entered: " << nAge << endl;
        
    }
    
    //先将数字作为字符处理
    void TestNumToString(){
        
        int nAge;
        
        while (1) {
            
            cout << "Enter your age: ";
            string strAge;
            cin >> strAge;
            
            //检查每个字符是否是数字
            bool bValid = true;
            
            for (int i = 0; i < strAge.length(); ++i) {
                
                if (!isdigit(strAge[i])) {
                    bValid = false;
                    break;
                }
                
            }
            
            if (!bValid) {
                continue;
            }
            
            stringstream ss;
            
            ss << strAge;
            
            ss >> nAge;
            
            if (nAge <= 0) {
                continue;
            }
         
            break;
        }
        
        cout << "You entered: " << nAge << endl;
        
    }
    
};

#endif /* streamStatus_hpp */
